git option in config should be an enumeration
authorWesley Wiser <wwiser@gmail.com>
Mon, 5 Jan 2015 01:59:43 +0000 (20:59 -0500)
committerWesley Wiser <wwiser@gmail.com>
Tue, 6 Jan 2015 02:04:06 +0000 (21:04 -0500)
The option in ~/.cargo/config is now called `vcs` and has the following
options: "git", "hg", and "none". This corresponds to the options for
the --vcs argument to `cargo new`.

This also fixes detection for hg repositories. Previously, we only tried
to discover if the working directory was contained in a git repository.
If it was, we would skip creating a git repo. Now, we check if the
working directory is contained in either a git or mecurial repo. If it
is, we skip creating a new repo.

Fixes #1116

src/bin/new.rs
src/cargo/ops/cargo_new.rs
src/cargo/ops/mod.rs
src/cargo/util/vcs.rs
src/doc/config.md

index 2fb43478cfde4fa105a02dfd43bc9e53cbf9f91c..bf355ccab312f736a814848985b83b089cfbbed0 100644 (file)
@@ -1,34 +1,16 @@
 use std::os;
-use rustc_serialize::{Decodable, Decoder};
 
 use cargo::ops;
 use cargo::core::MultiShell;
 use cargo::util::{CliResult, CliError};
 
-#[deriving(Show, PartialEq)]
-enum VersionControl { Git, Hg, NoVcs }
-
-impl<E, D: Decoder<E>> Decodable<D, E> for VersionControl {
-    fn decode(d: &mut D) -> Result<VersionControl, E> {
-        Ok(match try!(d.read_str()).as_slice() {
-            "git" => VersionControl::Git,
-            "hg" => VersionControl::Hg,
-            "none" => VersionControl::NoVcs,
-            n => {
-                let err = format!("could not decode '{}' as version control", n);
-                return Err(d.error(err.as_slice()));
-            }
-        })
-    }
-}
-
 #[deriving(RustcDecodable)]
 struct Options {
     flag_verbose: bool,
     flag_bin: bool,
     flag_travis: bool,
     arg_path: String,
-    flag_vcs: Option<VersionControl>,
+    flag_vcs: Option<ops::VersionControl>,
 }
 
 pub const USAGE: &'static str = "
@@ -55,9 +37,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
     let Options { flag_travis, flag_bin, arg_path, flag_vcs, .. } = options;
 
     let opts = ops::NewOptions {
-        no_git: flag_vcs == Some(VersionControl::NoVcs),
-        git: flag_vcs == Some(VersionControl::Git),
-        hg: flag_vcs == Some(VersionControl::Hg),
+        version_control: flag_vcs,
         travis: flag_travis,
         path: arg_path.as_slice(),
         bin: flag_bin,
index 1fa52c7d1e6bed9f9a8e8f745eace0d720e73bf1..6291d54be787c51b6ff591e038e9cae35b11b9ea 100644 (file)
@@ -2,24 +2,41 @@ use std::os;
 use std::io::{mod, fs, File};
 use std::io::fs::PathExtensions;
 
+use rustc_serialize::{Decodable, Decoder};
+
 use git2::Config;
 
 use util::{GitRepo, HgRepo, CargoResult, human, ChainError, config, internal};
 use core::shell::MultiShell;
 
+#[deriving(Copy, Show, PartialEq)]
+pub enum VersionControl { Git, Hg, NoVcs }
+
 pub struct NewOptions<'a> {
-    pub no_git: bool,
-    pub git: bool,
-    pub hg: bool,
+    pub version_control: Option<VersionControl>,
     pub travis: bool,
     pub bin: bool,
     pub path: &'a str,
 }
 
+impl<E, D: Decoder<E>> Decodable<D, E> for VersionControl {
+    fn decode(d: &mut D) -> Result<VersionControl, E> {
+        Ok(match try!(d.read_str()).as_slice() {
+            "git" => VersionControl::Git,
+            "hg" => VersionControl::Hg,
+            "none" => VersionControl::NoVcs,
+            n => {
+                let err = format!("could not decode '{}' as version control", n);
+                return Err(d.error(err.as_slice()));
+            }
+        })
+    }
+}
+
 struct CargoNewConfig {
     name: Option<String>,
     email: Option<String>,
-    git: Option<bool>,
+    version_control: Option<VersionControl>,
 }
 
 pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
@@ -41,28 +58,38 @@ pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
     })
 }
 
-fn existing_git_repo(path: &Path) -> bool {
-    GitRepo::discover(path).is_ok()
+fn existing_vcs_repo(path: &Path) -> bool {
+    GitRepo::discover(path).is_ok() || HgRepo::discover(path).is_ok()
 }
 
 fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {
     let cfg = try!(global_config());
     let mut ignore = "/target\n".to_string();
-    let no_git = !opts.git && (opts.no_git || cfg.git == Some(false));
-    let in_existing_git_repo = existing_git_repo(&path.dir_path());
+    let in_existing_vcs_repo = existing_vcs_repo(&path.dir_path());
     if !opts.bin {
         ignore.push_str("/Cargo.lock\n");
     }
 
-    if opts.hg {
-        try!(HgRepo::init(path));
-        try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes()));
-    } else if no_git || in_existing_git_repo {
-        try!(fs::mkdir(path, io::USER_RWX));
-    } else {
-        try!(GitRepo::init(path));
-        try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes()));
-    }
+    let vcs = match (opts.version_control, cfg.version_control, in_existing_vcs_repo) {
+        (None, None, false) => VersionControl::Git,
+        (None, Some(option), false) => option,
+        (Some(option), _, false) => option,
+        (_, _, true) => VersionControl::NoVcs,
+    };
+
+    match vcs {
+        VersionControl::Git => {
+            try!(GitRepo::init(path));
+            try!(File::create(&path.join(".gitignore")).write(ignore.as_bytes()));
+        },
+        VersionControl::Hg => {
+            try!(HgRepo::init(path));
+            try!(File::create(&path.join(".hgignore")).write(ignore.as_bytes()));
+        },
+        VersionControl::NoVcs => {
+            try!(fs::mkdir(path, io::USER_RWX));
+        },
+    };
 
     let (author_name, email) = try!(discover_author());
     // Hoo boy, sure glad we've got exhaustivenes checking behind us.
@@ -134,7 +161,7 @@ fn global_config() -> CargoResult<CargoNewConfig> {
     let mut cfg = CargoNewConfig {
         name: None,
         email: None,
-        git: None,
+        version_control: None,
     };
     let cargo_new = match user_configs.get("cargo-new") {
         None => return Ok(cfg),
@@ -158,12 +185,20 @@ fn global_config() -> CargoResult<CargoNewConfig> {
             })).0.to_string())
         }
     };
-    cfg.git = match cargo_new.get("git") {
+    cfg.version_control = match cargo_new.get("vcs") {
         None => None,
-        Some(git) => {
-            Some(try!(git.boolean().chain_error(|| {
-                internal("invalid configuration for key `cargo-new.git`")
-            })).0)
+        Some(vcs) => {
+            let vcs_str = try!(vcs.string().chain_error(|| {
+                internal("invalid configuration for key `cargo-new.vcs`")
+            })).0;
+            let version_control = match vcs_str.as_slice() {
+                "git" => VersionControl::Git,
+                "hg"  => VersionControl::Hg,
+                "none"=> VersionControl::NoVcs,
+                _  => return Err(internal("invalid configuration for key `cargo-new.vcs`")),
+            };
+
+            Some(version_control)
         }
     };
 
index 53ade356e9f55c2843a526eb5ace5c27a1fa389c..79140527ac104ae6ef050186df89203b2b0eea47 100644 (file)
@@ -6,7 +6,7 @@ pub use self::cargo_rustc::{Context, LayoutProxy};
 pub use self::cargo_rustc::Platform;
 pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig};
 pub use self::cargo_run::run;
-pub use self::cargo_new::{new, NewOptions};
+pub use self::cargo_new::{new, NewOptions, VersionControl};
 pub use self::cargo_doc::{doc, DocOptions};
 pub use self::cargo_generate_lockfile::{generate_lockfile};
 pub use self::cargo_generate_lockfile::{update_lockfile};
index f18d6dcc4f662f6bb833b401e1185664173f7661..7847a75bbb66bf40ba3d073af01cc317b646cc01 100644 (file)
@@ -23,4 +23,9 @@ impl HgRepo {
         try!(try!(process("hg")).arg("init").arg(path_str).exec());
         return Ok(HgRepo)
     }
+    pub fn discover(path: &Path) -> CargoResult<HgRepo> {
+        try!(try!(process("hg")).arg("root").cwd(path.clone()).exec_with_output());
+        return Ok(HgRepo)
+    }
 }
+
index fa6a69e57d5bd4be3e3942ced3840a5e3bd21e87..e7b6e33e249bbcae60aea467f3ec7124b358062f 100644 (file)
@@ -45,8 +45,8 @@ name = "..."
 email = "..."
 
 # By default `cargo new` will initialize a new git repository. This key can be
-# set to `false` to disable this behavior.
-git = true
+# set to `none` to disable this behavior.
+vcs = "none"
 
 # For the following sections, $triple refers to any valid target triple, not the
 # literal string "$triple", and it will apply whenever that target triple is